var LoginController = function(user){
	var thisController = this;
	
	thisController.loginModel = new LoginModel();
	thisController.loginView = new LoginView();
	
	var subscribeFunctions = function(){
		thisController.loginView.onLogin.subscribe(sendLogin);
		thisController.loginView.onLogOut.subscribe(doLogOut);
		thisController.loginView.onNewRequest.subscribe(doNewRequest);
		thisController.loginView.onEnvSelectChange.subscribe(doEnvSelectChange);
		
		thisController.loginModel.onLoad.subscribe(doLoad);
		thisController.loginModel.onLogin.subscribe(doLogin);
		thisController.loginModel.onLoginError.subscribe(doLoginError);
	};
	
	var doLoad = function(environments){
		var array = new Array();
		for (var i = 0; i < environments.length; i++) {
			array[i] = environments[i].host;
		}
		thisController.loginView.setEnvironments(array);
	};
	
	var sendLogin = function(loginParameters){
		var selectedEnv = loginParameters.environment;
		var environment = thisController.loginModel._environments[selectedEnv];
		var environmentCopy = {'scheme': loginParameters.scheme, 'host': environment.host, 'consumer': environment.consumer, 'oauth': environment.oauth};
		thisController.loginModel.sendLogin(loginParameters.username, loginParameters.password, environmentCopy);
	};
	
	var doLogin = function(user) {
		thisController.loginView.setLoggedIn(user);
		thisController.onLogin();
	};
	
	var doLoginError = function(loginError) {
		thisController.loginView.onLogginError(loginError.status, loginError.response);
		doLogOut();
	};
	
	var doLogOut = function(){
		thisController.loginView.setLoggedOut();
		thisController.onLogOut();
	};
	
	var doNewRequest = function(loginParams){
		var environment = thisController.loginModel._environment;
		var accessKeys = thisController.loginModel._user;
		var user = {'username': loginParams.username, 'selectedEnv': loginParams.selectedEnv, 'environment': environment, 'accessKeys': accessKeys };
		var loggedUser = JSON.stringify(user).replace("\n\r", "");
		thisController.loginView.newRequest(loggedUser);
	};
	
	var doEnvSelectChange = function(selectedEnv){
		var environment = thisController.loginModel._environments[selectedEnv];
		thisController.loginView.setSelectedScheme(environment.scheme);
	};
	
	this.loggedIn = function(user){
		thisController.loginModel.setLogin(user.accessKeys, user.environment);
		thisController.loginView.setPreviouslyLoggedIn(user.username, user.selectedEnv, user.accessKeys, user.environment.scheme);
	};
	
	this.onLogin = new Subscribable(function(){
		return {'user' : thisController.loginModel._user, 'environment': thisController.loginModel._environment};
	});

	this.onLogOut = new Subscribable(function(){
	});
	
	subscribeFunctions();
	this.loginModel.load();
	doLogOut();
};
//--------------------------------------------------------------------------------------------------------
var RequestController = function(loginController){
	var thisController = this;
	
	this.apiServiceView = new ApiServiceView();
	
	this.requestModel = new RequestModel();
	this.requestView = new RequestView();

	
	var subscribeFunctions = function(){
		loginController.onLogOut.subscribe(doLoggedOut);
		loginController.onLogin.subscribe(doLoggedIn);
		
		thisController.apiServiceView.onApiSelected.subscribe(doApiSelected);
		thisController.apiServiceView.onServiceSelected.subscribe(doServiceSelected);
		
		thisController.requestModel.onLoadApiVersion.subscribe(doLoadApiVersion);
		thisController.requestModel.onLoad.subscribe(doLoadServices);
		
		thisController.requestView.onSendRequest.subscribe(doSendRequest);
		
		thisController.requestModel.onLoadService.subscribe(doLoadRequest);
	};
	
	var doLoggedOut = function(){
		thisController.apiServiceView.enable(false);
		thisController.requestView.enable(false);
	};
	
	var doLoggedIn = function(loginParams) {
		thisController._loginParams = loginParams;
		thisController.apiServiceView.enable(true);
	};
	
	var doLoadApiVersion = function(apiVersion){
		thisController.apiServiceView.setApiVersion(apiVersion);
	};
	
	var doApiSelected = function(apiIndex){
		var api = thisController.requestModel._services[apiIndex];
		thisController._api = api;
		var services = api.services;
		var array = new Array();
		for (var i = 0; i < services.length; i++) {
			array[i] = services[i];
		}
		thisController.apiServiceView.setServices(array);
	};
	
	var doLoadServices = function(apiServices){
		var array = new Array();
		for (var i = 0; i < apiServices.length; i++) {
			array[i] = apiServices[i].api;
		}
		thisController.apiServiceView.setApis(array);
		doApiSelected(0);
	};
	
	var doServiceSelected = function(service){
		var api = thisController.requestModel._services[service.apiIndex];
		var apiService = api.services[service.serviceIndex];
		thisController.requestModel.loadService(api.api, apiService);
	};
	
	var doLoadRequest = function(service){
		
		var restParams = service.rest.parameters;
		var reflectionParams = service.reflection.parameters;
		
		var array = new Array();
		for (var i = 0; i < restParams.length; i++) {
			var isFile = (reflectionParams[i].type == "InputStream");
			array[i] = {'name': restParams[i].name, 'isFile': isFile};
		}
		thisController.requestView.setFields(array);
		
		for (var i = 0; i < restParams.length; i++) {
			var type = reflectionParams[i].type;
			if(reflectionParams[i].genericTypes){
				var generic = reflectionParams[i].genericTypes[0];
				type += '&lt;' + generic.type + '&gt;';
				if(generic.enum && reflectionParams[i].type == "List"){
					var enumValues = thisController.requestModel._enums[generic.type];
					thisController.requestView.setListEnumValues(restParams[i].name, enumValues);
				}
			}
			thisController.requestView.setFieldType(restParams[i].name, type);
			if(reflectionParams[i].enum){
				var enumValues = thisController.requestModel._enums[reflectionParams[i].type];
				thisController.requestView.setEnumValues(restParams[i].name, enumValues);
			}
			if(restParams[i].defaultValue){
				thisController.requestView.setDefaultValue(restParams[i].name, restParams[i].defaultValue);
			}
			if(!restParams[i].notNull){
				thisController.requestView.setFieldNull(true, restParams[i].name);
			}
			if(restParams[i].name == "oauthtoken"){
				var access = thisController._loginParams.user.accessKey;
				thisController.requestView.setFieldValue(restParams[i].name, access);
			}
			if(reflectionParams[i].type == "InputStream"){
				thisController.requestView.setFileEvents(restParams[i].name);
			}
		}
		thisController.requestView.setLabel({'verb':service.rest.verb, 'path': service.rest.path, 'deprecated': service.reflection.deprecated});
		var multipart = (service.rest.consumes && service.rest.consumes[0] == "multipart/form-data");
		thisController.requestView.setMultipartRequest(multipart);
		setJavadocLink(service.reflection.name, service.reflection.parameters);
		thisController.requestView.enable(true);
	};
	
	var doSendRequest = function(sendParams){
		var service = thisController.requestModel._service;
		var environment = thisController._loginParams.environment;
		if(service.rest.consumes && service.rest.consumes[0] == "multipart/form-data"){
			var path = environment.scheme + "://" + environment.host + service.rest.path;
			var formParams = {};
			var restParams = service.rest.parameters;
			for (var i = 0; i < restParams.length; i++) {
				var name = restParams[i].name;
				if(restParams[i].type == "PATH"){
					var value = sendParams.parameters[name];
					path = path.replace("\{" + name + "\}", value);
				}
				else if(restParams[i].type == "FORM"){
					formParams[name] = restParams[i];
				}
			}
			thisController.requestView.setMultipart(path, formParams);
		}
		else{
			var user = thisController._loginParams.user;
			var requestData = {'environment': environment, 'service': service.rest, 'user': user, 'parameters': sendParams.parameters, 'iterations': sendParams.iterations};
			var request = JSON.stringify(requestData);
			request = request.replace("\n\r", "");
			thisController.requestView.setNormalRequest(request);
		}
	};
	
	var setJavadocLink = function(serviceName, parameters){
		var apiName = thisController._api.api;
		var paramsList = "";
		for(parameter in parameters){
			paramsList += parameters[parameter].typeClass + ", ";
		}
		if(parameters.length > 0){
			paramsList = paramsList.substring(0, paramsList.length - 2);
		}
		var linkPath = "doc/com/zyncro/api/" + apiName + ".html#" + serviceName + "(" + paramsList + ")";
		thisController.requestView.setJavadocLink(linkPath);
	};
	
	subscribeFunctions();
	this.requestModel.load();
	this.requestModel.loadEnums();
	this.requestModel.loadApiVersion();
	doLoggedOut();
};
//----------------------------------------------------------------------------------------------------
var ResponseController = function(request){
	var thisController = this;
	
	this._request = request;
	
	this.responseModel = new ResponseModel();
	this.responseView = new ResponseView();
	
	var subscribeFunctions = function(){		
		thisController.responseModel.onResponse.subscribe(doResponse);
		thisController.responseModel.onResponse.subscribe(doIterations);
	};
	
	var doResponse = function(data){
		var response = data.response;
		var produces = thisController._request.service.produces;
		var isHtml = false;
		if(response && response != "" && (produces && produces[0] == "application/json")){
			try{
				var jsonObj = JSON.parse(data.response);
				response = JSON.stringify(jsonObj, null, 4);
			}
			catch(exception){
				isHtml = true;
			}
		}
		thisController.responseView.setResponse(data.status, response, data.time, isHtml);
	};
	
	
	var doIterations = function(){
		var iterations = thisController._request.iterations;
		if(iterations && iterations.from < iterations.to){
			iterations.from = new Number(iterations.from) + 1;
			doSendRequest();
		}
	};

	var doSendRequest = function(){
		var env = thisController._request.environment;
		var service = thisController._request.service;
		var user = thisController._request.user;
		var params = {};
		var iters = thisController._request.iterations;
		
		if(iters){
			for(param in thisController._request.parameters){
				params[param] = thisController._request.parameters[param].replace("%s", iters.from);
			}
		}
		else{
			params = thisController._request.parameters;
		}
		
		thisController.responseView.doLoad(env, service, user, params, iters);
		thisController.responseModel.sendRequest(env, service, user, params);
	};
	
	subscribeFunctions();
	doSendRequest();
};